home *** CD-ROM | disk | FTP | other *** search
- ViewPoint(TM)
- -------------
-
- Howdy. I hate stupid ads. I think marketing hype and stuff that looks like
- it belongs on a cerial box belong in this category. So this is not an ad
- in the usual sence of the word. I'll stay away from hype and slogans and
- just tell you about the library, programmer to programmer.
-
- First some basics: the "C++ ViewPoint Graphics Library -- Essential
- Drawing Components" is a rendering library for PC's. It is easy to use,
- powerful, and fast.
-
- -------------------------------
-
- I interrupt this prose to bring you an example, to show the overall
- flavor of the library. Here is a graphical equivilent of a "hello world"
- program-- one that shows you can compile and link and do something simple.
- This draws a square with an X in the middle, centered in the screen. It
- is mostly housekeeping and overhead, since the program itself does not
- do much.
-
-
- #include "usual.h"
- #include "vp.h"
- #include "device.h"
- #include "getkey.h"
-
- screen_device d ("vga.drv");
-
- int main()
- {
- if (!d.init()) return 3; //go into graphics mode
- viewport v (d); //the whole screen
- v.set_scale (0,0,999,999);
- v.rectangle (333,333, 666,666);
- v.line (400,400, 600,600);
- v.line (400,600, 600,400);
- key::get(); //pause
- }
-
-
- First, look at the include files. USUAL.H is included in every source
- file. VP.H is included for the viewport class, and DEVICE.H is
- included for the device class and its derived type, the screen_device.
- The last include file, GETKEY.H, is to supply the key class used
- in the example to pause and wait for a keypress.
-
- The next line defines `d', a screen_device. The screen device is a
- shell around loadable device drivers, and the constructor will load the
- named driver.
-
- The first line in main() is a call to device::init() which will activate
- the driver. A parameter can be given to specify which mode to use, as a
- driver may support a number of different graphics modes. In this case
- no parameter is used so it will take the default as recorded in the
- driver file itself. It returns FALSE if not successful.
-
- After calling init(), `d' is an active device, and any rendering primitives
- (member functions of class device) can be used on it. However, these drawing
- functions really are quite primitive, and they use absolute device pixels.
-
- Depending on which driver you used, the number of pixels on the screen can
- vary. So drawing a rectangle in the center will require some calculation.
- You can find out what the resolution of the display is with d.xmax()
- and d.ymax(), and use some computations in every point you plot to
- adjust it to the actual display size. That is quite a pain.
-
- So the library offers "world coordinates" which is basically a way to have
- the library do all that calculation for you. The viewport is a higher
- level class which has this ability.
-
- A viewport is attached to some device. Line 11 defines `v' to be a
- viewport attached to `d' and taking up the whole screen. Now you can
- use the high level commands in v instead of the low level commands in d,
- but the scaling problem still remains-- the pixels in v are exactly the
- same as those in d.
-
- The next line solves this. Instead of having to adapt my code to deal
- with whatever display resolution is at run time, I turn it around and tell
- it what size coordinate system I want to use. The call to v.set_scale()
- specifies what I want to call the upper left and lower right pixels in the
- viewport. Now, all uses of v will use the resolution I specified,
- automatically mapping it to the physical device.
-
- The next line draws a rectangle, centered in the 1000x1000 viewport.
- The following draw the diagonal lines to form the X. The last
- waits for a keypress.
-
- Note that there is no code for cleaning up. When v goes out of scope, the
- viewport is destroyed. When d goes out of scope (at program termination)
- its destructor will put the screen back in text mode, as if d.finish()
- was called.
-
- -------------------------------
-
- The 17 line example above should give you some idea of how it is set up.
- There is a low level device class and a high level viewport class.
-
- The device class offers primitive commands. There are command for reading
- device information (like what the resolution is), color and palette
- control, display control, and rendering.
-
- The color commands can deal with 32 bit color. Many other libraries are
- locked into 8 bit pixels. But the future of PC graphics offers more
- advanced abilities than this. Since 32 bit numbers are less efficient
- to manipulate, the library can be compiled to deal with 8, 16 or 32
- bit values (16 is the default). Code compiled with one option can be
- linked with code compiled with another setting. With ViewPoint, you can
- use advanced features like the Siearra Hi-Color DAC with 32768 colors.
- Color may be mapped, and there are functions to set up the palette.
- The palette control will do the best it can for the device in use. The
- BGI, for example, uses different commands for EGA and VGA color settings!
- The VP's device class is intended to abstract the device, so this one
- function will set palette mapping in the best way for whatever device.
-
- The rendering functions include pixels, lines, rectangles, flood filling,
- and block moves. They are all pretty simple, like read_pixel(x,y) or
- line (style, x1,y1,x2,y2). You would find using functions on this level
- to be very much like using other graphics libraries.
-
- But you normally don't use the device rendering functions. Rather, you
- use the viewport rendering functions, which are themselves implemented
- using the device's.
-
- A viewport is a higher level entity than an device. It belongs to some
- device, so drawing with the viewport will make stuff appear on that
- device. It also holds a style and a coordinate system.
-
- All the device rendering commands take a style as the first parameter.
- The viewport holds a style and implies this style, so you don't specify
- it each time.
-
- A viewport does coordinate transformations. Rather than plotting in
- device pixels, you can use any kind of coordinate system you like. The
- program above could pretend that the screen was 1000x1000 and use
- constants for all its positions, even though this program will run on
- any kind of device at all. That is a simple example. Coordinate
- systems can be rotated and skewed. See the SEGMENT demo program.
-
- The viewport also has more drawing functions, and they are friendlier.
- While a device has
- void device::line (const gfxstyle&, int x1,int y1, int x2,int y2);
- A viewport has
- // absolute
- viewport& line (int x1,int y1, int x2,int y2);
- viewport& line (const pair& p1, const pair& p2);
- viewport& line (const rect& r);
- viewport& line (int x, int y);
- viewport& line (const pair& p2);
- viewport& movecp (int x1, int y1);
- viewport& movecp (const pair& p);
- // relative
- viewport& line_rel (int deltax, int deltay);
- viewport& line_rel (const pair& delta);
- viewport& up (int dist);
- viewport& down (int dist);
- viewport& left (int dist);
- viewport& right (int dist);
- viewport& movecp_rel (int deltax, int deltay);
- viewport& movecp_rel (const pair& p);
- // polylines
- viewport& polyline (int count, const int* data); //absolute
- viewport& polyline (int count, const pair* data); //absolute
- viewport& polyline_rel (int count, const int* data, int x, int y);
- viewport& polyline_rel (int count, const int* data, const pair& start);
- viewport& polyline_rel (int count, const pair* data, int x, int y);
- viewport& polyline_rel (int count, const pair* data, const pair& start);
-
- Of these 21 functions, 5 of them are called `line'. Thanks to overloading
- in C++, the library can be easier to use. It is quite practical to have
- 5 different line functions since you don't have to remember 5 different
- names. You just give it whatever kind of data you happen to have on
- hand for its parameters. In this case, you can feed it 4 ints, (x and y
- source and dest), 2 ints (x and y of the dest, continues from where the
- last one left off), 2 pairs, one pair (dest only), or a rectangle.
- It makes the library easy to use because you can use the data you have
- on hand rather than keeping it in the form the library likes, or having
- to convert it.
-
- When you draw a line, it will appear in some color or colors, using some
- logical operation and some pattern. All this is in the style structure.
- Each viewport has its own style. In the first example program, the color
- of the drawing could have been specified by saying
- v.style.FPen= 7; // forground pen is white
- or somesuch. There is an FPen (forground pen) and a BPen (background pen).
- You can set a 16 bit line pattern. There are two ways the line pattern
- is applied. In all cases 1's in the pattern are drawn using the FPen.
- You have your choice with the 0's. They can be transparent or drawn using
- BPen. In all cases, a logic operation can also be applied to all pixel
- drawn: REPLACE, AND, OR, or XOR.
-
- When drawing a polyline, the line pattern is continuous across the whole
- thing. It does not start over with each segment, like most other libraries
- do. This is a general ability: the style can be set to preserve line
- patterns in progress across multiple calls, so lines connect smoothly.
- Patterns are applied to curves too.
-
- Another fine touch for using patterns is the "open interval". Say you
- draw from A to B and then from B to C. Point B is drawn twice. If you
- are using XOR mode, that is bad. If you are trying to make your line
- pattern continuous across the segments, that is bad. With an open
- interval, the second line does not draw from B to C but skipps the first
- pixel. B is not drawn twice. With diagonal lines and scaled coordinate
- systems, this would be nearly impossible to do manually. But ViewPoint
- supports it as a low level primitive, where it belongs.
-
- There are other fields in the style for dealing with filled shapes. A
- filled shape can be drawn in a solid color using the FPen. Or it can use
- a fill pattern. The pattern can be any size, though drivers can impose an
- allingment restriction (width must be a multiple of 8, for example).
- The fill pattern can take two forms. A one plane fill pattern is just like
- the line pattern in two dimentions. That is, it uses FPen for the 1's and
- your choice of BPen or transparent for the 0's. Or a fill pattern can be
- full color. In all cases, the logic modes apply.
-
- Fill patterns work the same way on all filled shapes-- rectangles, polygons,
- ellipses, even flood filling.
-
- You might think a rectangle is pretty simple. But with a rotated or
- skewed coordinate system the rectangle can appear diamond shaped.
- Naturally it handles all this by itself. But that is simple.
-
- Filled polygons are more interesting. The viewport class has 6 forms of
- the filled_polygon() function. Paramters can be arrays of ints or
- pairs, and a starting point can be specified as 2 ints or a pair or left
- out. Polygons are very difficult to do "right" in raster graphics.
- ViewPoint implements correct meshing polygons. That is, two polygons that
- have the same edge in common will mesh together seemlessly. No pixel is
- drawn twice. Only points that are strictly on the inside of the polygon
- are drawn, and a a decision process is used to handle points on the
- edges and corners. This means that a polygon mesh can be drawn to form
- complex shapes. Furthermore, the implementation is fast. It was timed
- reciently as being over 30% faster than BGI's filled polygons, and their's
- are "sloppy".
-
- But sometimes you don't want meshing polygons. For a single polygon
- sitting out there by itself, it can appear "shaved". You want it to
- round off rather than rounding in. You don't want the left corner pixel
- to be zapped. So you can also specify polygons with Bresenham edges.
- That is, the polygon will exactly fit over a set of ordinary lines drawn
- between the same points.
-
- There are 21 ways to draw lines, 6 to draw filled polygons. And that is
- just counting the function calls, not the variations in the `mode'
- parameter for polys or all the differnet settings in the style.
- How many ways can you draw ellipses and ellipse related things? More than
- a few dozen... more like hundreds!
-
- You can specify center-radii, specify bounding boxes in several different
- ways, and so on. Then you can draw an arc or the whole thing, where the
- arc can be specified in several different ways. The number of functions
- needed was into the double digits at the minimum.
-
- So a better way was invented. The different properties of the rendering
- call are specified by individual calls, and several forms of each are
- available. This means that the total number of effective calls is equal
- to the product of the numbers of its parts.
-
- Here are some examples:
- v.ellipse(center,rad_x,rad_y).draw(); //draw whole ellipse
- v.ellipse(bounding_box).arc(angle1,angle2).draw(); //draw arc
-
- Notice that the second line is three functions. The first call, ellipse(),
- could have used several (6) different forms to specify the same shape.
- The second call, arc(), could have used 2 different forms or be left
- out entirely to draw the whole thing. And finally, the third call, draw(),
- does the rendering of the built-up definition. Instead of draw() you could
- have used filled() or pieslice() or others. This paragraph touched on
- 54 (though only 48 are useful) effective rendering functions.
-
- Viewports support flood fills. As you've probably guessed by now, there
- are several ways to do it. First of all, it uses the fill pattern and
- style stuff the same way as any other filled shape. Even if you are
- filling with a pattern and a logical operation that turns into the border
- color, or that does nothing, it will not get confused. Any shape can be
- filled properly no matter what modes, colors, or styles are in use.
- You can have flood fill search out a border color and stop at the border.
- Or you can have it fill over a region of a color and stop when it hits
- something that is not that color. For simpler fills, you can specify the
- fast fill mode which does not work with arbitrary shapes but is just
- fine for convex shapes and is much faster. There is also a change_color()
- function that will change all pixels of one color inside a specified
- rectangle into another color. This function is extremely fast, and is
- great for things like hilighting menu choices.
-
- There are move and scroll functions that copy stuff from one place on the
- screen to another. Naturally, there are lots of choices on parameters
- and modes.
-
- Moving is really a special case of bitmap manipulation-- GET and PUT
- functions. Bitmaps are a major part of the ViewPoint library, and they
- even have their own class. Class pixarray has over three dozen functions
- in it.
-
- A pixarray holds a bitmap image. It does its own memory management, and
- will use the far heap even in a small model program. You don't have to
- allocate memory for it-- that is automatic. GETing an image is as simple
- as: pix= v.get(r);
- where pix is a pixarray, v is a viewport, and r is a rect. You can use
- different forms for the paramters besides a rect. This shows that
- bitmaps can be used in an expressive way-- they can be used in expressions
- as high level objects.
-
- The flip side of a get is a put. Just putting a pixarray at some position
- would be too boreing. Using the logical operations is better. But
- there is even more variety: you can put just part of a pixarray, and
- magnify while putting, or both.
-
- Besides a place to hold an image between a get and a put, class pixarray
- can be used to manipulate the image. A simple example is to recolor
- it. You can map one set of colors onto another, or extract individual
- colors. You can query the pixarray for its size and other info, and
- read and write individual pixels within it, and even copy parts from
- one bitmap to another. A more exotic function is ortho_transform()
- which is really 8 functions rolled into one. It can mirror, transpose,
- and rotate (in 90 degree increments) an image.
- There are also functions to load and save pixarrays to disk files.
-
- This should give you a general feeling for the concepts the library is
- founded on. But it is just scratching the surface. There is support
- for text that lets you have different kinds of fonts and is very
- extendable. And the mouse! The "intelligent mouse classes" are deserving
- of their own demonstration. You've never seen anything like it!
-
- So check it out! You can have all this for $220 plus shipping. It
- includes full source code. Tech support is good. Updates and bug
- fixes are available online. There is a 60 day satisfaction guarantee.
-
- John M. Dlugosz
- CIS: 70007,4657
-
- Dlugosz Software
- PO Box 876506
- Plano TX 75086
- (214)618-2023
-